﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Belmost4PDA.DatabaseWorkPDA;
using Belmost4PDA.Fasade;

namespace Belmost4PDA.Logic
{
    /// <summary>
    /// Класс для древовидного представления текущего моста. Заведует также и загрузкой данных
    /// </summary>
    public class brElement
    {
        // Информация по элементу (заполняеться в GetTree)
        public string Name;
        public ElementItem elmItem;
        public int ID, parentID;
        // дочерние элементы
        public List<brElement> Child = new List<brElement>();
        // маркер что этот эелемент еще не присутсвует в базе 
        public bool isNewElem = false;
        //для тех элементов, которые таки не надо удалять
        //public bool NotDeleteMe = false;
        /// <summary>
        /// Загружает элементы из базы и формирует дерево (во главе основной узел)
        /// </summary>
        /// <returns></returns>
        public static brElement GetTree()
        {
            /// создать топ элемент 
            brElement Top = new brElement();
            Top.Name = "Корень";
            Top.elmItem = null;
            Top.ID = 0;
            /// получить список записей из ElementReader
            /// создать из него список (List) записей brElement (Name ассоциировать c cName если cName=="" то с Name)
            /// используя Вункцию AddToChild добавить все элементы в Top
            List<ElementItem> list = ElementsReader.GetItemForBridge(GlobalStates.IDBR);
            foreach (ElementItem item in list)
            {
               brElement britem=new brElement();
               britem.ID = item.ID;
               britem.parentID = item.IDParent;
               if (item.cName != "") britem.Name = item.Name + "(" + item.cName + ")";
               else britem.Name = item.Name;
               if (item.NameSuf != "")
                   //suff in the beginning
                   britem.Name =item.NameSuf + "  " + britem.Name;
               britem.elmItem=item;
               Top.AddToChild(britem);
            }
            return Top;
        }

        /// <summary>
        /// Add to child.
        /// </summary>
        /// <param name="child">The child.</param>
        public void AddToChild(brElement child)
        {
            if (!AddToExistChild(child))
            {
                // не нашлось в дочерних
                List<brElement> newChild = new List<brElement>();
                foreach (brElement element in Child)
                {
                    if (element.parentID == child.ID)
                    {
                        child.Child.Add(element);
                    }
                    else
                    {
                        newChild.Add(element);
                    }
                }
                Child = newChild;
                Child.Add(child);
            }
            else
            {
                List<brElement> newChild = new List<brElement>();
                foreach (brElement element in Child)
                {
                    if (element.parentID == child.ID)
                    {
                        child.Child.Add(element);
                    }
                    else
                    {
                        newChild.Add(element);
                    }
                }
                Child = newChild;
            }
        }


        /// <summary>
        /// Поиск чайлдов у которых id == idparent.
        /// </summary>
        /// <param name="child">The child.</param>
        /// <returns>возвращает true если нашлось куда вставить</returns>
        public bool AddToExistChild(brElement child)
        {
            /// перебор чайлдов
            ///   для каждого проверить равен для ID и child.parentID
            ///   если да то добавить к его дочерним child. вернуть true (и закончить перебор)
            /// перебор чайлдов
            ///   для каждого вызвать AddToExistChild(child) и если вернулся true то вернуть true (и закончить перебор)  
            /// вернуть false
            /// ps. переборы не совмещать

            foreach (brElement element in Child)
            {
                if(element.ID == child.parentID)
                {
                    //element.AddToChild(child);
                    element.Child.Add(child);
                    return true;
                }
            }

            foreach (brElement element in Child)
            {
                if (element.AddToExistChild(child))
                {
                    return true;
                }
            }
            return false;
        }

        public List<brDef> defList = null;
        /// <summary>
        /// Создает контролы для редактирования дефектов выбранного элемента и выводит их на окно
        /// </summary>
        /// <param name="_form">The _form.</param>
        public void CreateDefWindow(Form _form)
        {
            if(defList==null)
            {
                defList = brDef.GetDefForElem(elmItem, this);
            }
            //Label with all defects on form
            Label l = new Label();
            string CurrentSuf, CurrentName;
            QuerySelect q=new QuerySelect();
            q.Select("select namesuf,elmcode from BrElm where idbrelm= " + elmItem.IDParent);
            List<DataRows.DataRows> lst = q.GetRows();
            CurrentSuf = lst[0].FieldByName("NameSuf").Replace(" ", "");
            q.Select("select elmname from ElmBM where elmcode= " + lst[0].FieldByName("elmcode"));
            lst = q.GetRows();
            CurrentName = lst[0].FieldByName("elmname");
            l.Text = Name+ " ("+ CurrentSuf+" " +CurrentName+")";
            l.BackColor=SystemColors.InactiveBorder;
            int RelY = (int)_form.Tag;
            RelY += 5;
            if (l.Text.Length > 33)
              l.Height = l.Height*2;
            l.Left = 5;
            l.Width = _form.Width - 10;
            l.Top = RelY;
            _form.Controls.Add(l);
            RelY += l.Height;
            _form.Tag = RelY;
            /// ....
            foreach (brDef def in defList)
            {
                def.CreateDefControls(_form);
            }
            /*
            foreach (brElement element in Child)
            {
                element.CreateDefWindow(_form);
            }*/
        }

        /// <summary>
        /// Сохраняет данные в базу (если есть такакя необходимость)
        /// </summary>
        public void PostData()
        {
            if(defList!=null)
            {
                foreach (brDef def in defList)
                {
                    def.Post();
                }
                defList.Clear();
            }
        }

        /// <summary>
        /// удалени
        /// </summary>
        public void Delete()
        {
            
            if(!isNewElem)
            {
                 //del chil
                foreach (brElement element in Child)
                {
                    //if(!NotDeleteMe)
                    element.Delete();
                }
                 //del item
                //if (!NotDeleteMe)
                ElementsReader.DelElem(ID, GlobalStates.IDBR);
            }
        }

        public static brElement GetNewItem(brElement topelement, int idnew, int elmclass, string suff)
        {
            brElement newElm = new brElement();
            newElm.isNewElem = true;
            topelement.Child.Add(newElm);
            newElm.parentID = topelement.ID;
            newElm.ID = -1;
            // надо получить запись ElmBM по коду idNew и у нее по если есть clsName то по коду elmClass имя
            newElm.elmItem = new ElementItem();
            newElm.elmItem.ID = -1;
            newElm.elmItem.IDParent = topelement.ID;
            newElm.elmItem.elmCode = idnew;
            newElm.elmItem.elmClass = elmclass;
            newElm.elmItem.NameSuf = suff;
            newElm.elmItem.bmItem = ElementsReader.ElmBm[idnew];
            newElm.elmItem.Name = newElm.elmItem.bmItem.Name;
            if (newElm.elmItem.bmItem.clsName != "")
            {
                newElm.elmItem.cName = newElm.elmItem.bmItem.GetCls()[elmclass];
                newElm.Name = newElm.elmItem.cName;
            }
            else
            {
                newElm.elmItem.cName = "";
                newElm.Name = newElm.elmItem.Name;
            }
            if (newElm.elmItem.NameSuf != "")
                newElm.Name += " " + newElm.elmItem.NameSuf;
            return newElm;
        }

        public void PostNewData()
        {
            if(isNewElem)
            {
                // вставко новой записи в BRElm
                int newID = ElementsReader.InsertNewElem(GlobalStates.IDBR, elmItem, ID);
                // вставко запсией в brdef
                ElementsReader.InsertNewDefItems(GlobalStates.IDBR, elmItem, newID);
                foreach(brElement element in Child)
                {
                     ElementsReader.UpdateElm(newID.ToString(), GlobalStates.IDBR.ToString(), element.ID.ToString());
                     //элементик просит, чтобы его не удаляли
                     //element.NotDeleteMe = true;
                }
            }
            foreach (brElement element in Child)
            {
                element.PostNewData();
            }
        }

        public bool TestValue()
        {
            if (defList != null)
                foreach (brDef def in defList)
                {
                    def.controls.FromControls();
                    if (!AbstractValueController.GetController(AbstractValueController.ControllerType.DefDouble, null).Check(def.controls.Value))
                        return false; // один из параметров не пошел

                }
            // запуск для чайлдов
            foreach (brElement element in Child)
            {
                if(!element.TestValue())
                    return false;
            }
            return true;
        }
    }
}

